home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2 Examples.sit / Raven 1.2 Examples / Quill / Source / PenDialog.cpp < prev    next >
Text File  |  1997-08-26  |  13KB  |  535 lines

  1. /*
  2.  *    File:        PenDialog.cpp
  3.  *    Function:    A dialog that allows the user to edit an SPen.
  4.  *    Written by:    Jesse Jones
  5.  *
  6.  *  Copyright ゥ 1997 Jesse Jones. 
  7.  *    For conditions of distribution and use, see copyright notice in ZTypes.h  
  8.  *
  9.  *    Change History (most recent first):
  10.  *
  11.  *         <1>     5/04/97    JDJ        Created
  12.  */
  13.  
  14. #include "PenDialog.h"
  15.  
  16. #include <Fp.h>
  17. #include <List.h>
  18. #include <Resources.h>
  19.  
  20. #include <ZApplication.h>
  21. #include <ZColorSwatch.h>
  22. #include <ZDialogHandler.h>
  23. #include <ZMenuBar.h>
  24. #include <ZNumbers.h>
  25. #include <ZPatternSwatch.h>
  26. #include <ZQDShapes.h>
  27. #include <ZStringUtils.h>
  28.  
  29. #include "ClickNotifier.h"
  30. #include "DialogBoxProxy.h"
  31. #include "WindowProxy.h"
  32.  
  33.  
  34. // ===================================================================================
  35. //    class CRandomWalk
  36. // ===================================================================================
  37. class CRandomWalk : public TPane {
  38.  
  39.     typedef TPane Inherited;
  40.  
  41. //-----------------------------------
  42. //    Initialization/Destruction
  43. //
  44. public:    
  45.     virtual             ~CRandomWalk();
  46.     
  47.                         CRandomWalk(TView* superView);
  48.     
  49.     static     MReanimatable* Create(MReanimatable* parent);
  50.  
  51. //-----------------------------------
  52. //    New API
  53. //
  54. public:
  55.             void         Restart();
  56.                         // Start walking all over again.
  57.  
  58.             void         SetPen(const SPen& pen);
  59.  
  60. //-----------------------------------
  61. //    Inherited API
  62. //
  63. protected:
  64.     virtual void         OnReanimated();
  65.     
  66.     virtual bool         OnMouseDown(const TMouseEvent& event);
  67.  
  68.     virtual void         OnDraw(TCanvas& canvas, const TRegion& dirtyRgn);
  69.  
  70. //-----------------------------------
  71. //    Member data
  72. //
  73. protected:
  74.     SPen            mPen;
  75.     list<TPoint, allocator<TPoint> > mPath;
  76. };
  77.  
  78. static TReanimatorRegister<CRandomWalk> sRandomWalkRegistrar;
  79.  
  80. //---------------------------------------------------------------
  81. //
  82. // CRandomWalk::~CRandomWalk    
  83. //
  84. //---------------------------------------------------------------
  85. CRandomWalk::~CRandomWalk()
  86. {
  87. }
  88.  
  89.  
  90. //---------------------------------------------------------------
  91. //
  92. // CRandomWalk::CRandomWalk    
  93. //
  94. //---------------------------------------------------------------
  95. CRandomWalk::CRandomWalk(TView* superView) : TPane(superView)
  96. {
  97. }
  98.  
  99.  
  100. //---------------------------------------------------------------
  101. //
  102. // CRandomWalk::Create                                    [static]
  103. //
  104. //---------------------------------------------------------------
  105. MReanimatable* CRandomWalk::Create(MReanimatable* parent)
  106. {
  107.     return new CRandomWalk(dynamic_cast<TView*>(parent));
  108. }
  109.  
  110.  
  111. //---------------------------------------------------------------
  112. //
  113. // CRandomWalk::SetPen
  114. //
  115. //---------------------------------------------------------------
  116. void CRandomWalk::SetPen(const SPen& pen)
  117. {
  118.     mPen = pen;
  119.     
  120.     this->Invalidate();
  121. }
  122.  
  123.  
  124. //---------------------------------------------------------------
  125. //
  126. // CRandomWalk::Restart
  127. //
  128. //---------------------------------------------------------------
  129. void CRandomWalk::Restart()
  130. {
  131.     mPath.resize(0);
  132.     
  133.     TRect extent = this->GetExtent();
  134.     short max = Max(extent.GetWidth()/10, extent.GetHeight()/10, 1);
  135.     
  136.     TPoint prevPt;
  137.     prevPt.h = extent.left + extent.GetWidth()/2;    // start in the center
  138.     prevPt.v = extent.top + extent.GetHeight()/2;
  139.     
  140.     mPath.push_back(prevPt);
  141.     
  142.     // Do a random walk until we exit the pane or we bounce around
  143.     // a hundred times.
  144.     bool hitEdge = false;
  145.     for (long index = 1; index <= 100 && !hitEdge; index++) {
  146.         short length = Random(max);
  147.         double angle = Random(2*pi);
  148.         
  149.         TPoint nextPt;
  150.         nextPt.h = prevPt.h + length*cos(angle);
  151.         nextPt.v = prevPt.v + length*sin(angle);
  152.         
  153.         hitEdge = !extent.Contains(nextPt);
  154.         mPath.push_back(nextPt);
  155.     
  156.         prevPt = nextPt;
  157.     }
  158.     
  159.     this->Invalidate();
  160. }
  161.  
  162.  
  163. //---------------------------------------------------------------
  164. //
  165. // CRandomWalk::OnReanimated
  166. //
  167. //---------------------------------------------------------------
  168. void CRandomWalk::OnReanimated()
  169. {
  170.     Inherited::OnReanimated();
  171.  
  172.     this->Restart();
  173. }
  174.  
  175.  
  176. //---------------------------------------------------------------
  177. //
  178. // CRandomWalk::OnMouseDown
  179. //
  180. //---------------------------------------------------------------
  181. bool CRandomWalk::OnMouseDown(const TMouseEvent& event)
  182. {
  183.     #pragma unused(event)
  184.     
  185.     this->Restart();
  186.     
  187.     return kHandled;
  188. }
  189.  
  190.  
  191. //---------------------------------------------------------------
  192. //
  193. // CRandomWalk::OnDraw
  194. //
  195. //---------------------------------------------------------------
  196. void CRandomWalk::OnDraw(TCanvas& canvas, const TRegion& dirtyRgn)
  197. {
  198.     #pragma unused(dirtyRgn)
  199.     
  200.     if (mPath.size() > 1) {
  201.         list<TPoint, allocator<TPoint> >::iterator iter = mPath.begin();
  202.         TPoint prev = *iter++;
  203.         
  204.         while (iter != mPath.end()) {
  205.             TPoint next = *iter++;
  206.             
  207.             TLineShape::Draw(canvas, prev, next, mPen);
  208.             
  209.             prev = next;
  210.         }
  211.     }
  212. }
  213.  
  214. #pragma mark -
  215.  
  216. // ===================================================================================
  217. //    class CPenDialog
  218. // ===================================================================================
  219.  
  220. static TReanimatorRegister<CPenDialog> sPenEditorRegistrar;
  221.  
  222. //---------------------------------------------------------------
  223. //
  224. // CPenDialog::~CPenDialog    
  225. //
  226. //---------------------------------------------------------------
  227. CPenDialog::~CPenDialog()
  228. {
  229. }
  230.  
  231.  
  232. //---------------------------------------------------------------
  233. //
  234. // CPenDialog::CPenDialog
  235. //
  236. //---------------------------------------------------------------
  237. CPenDialog::CPenDialog()
  238. {
  239. }
  240.  
  241.  
  242. //---------------------------------------------------------------
  243. //
  244. // CPenDialog::Create                                    [static]
  245. //
  246. //---------------------------------------------------------------
  247. MReanimatable* CPenDialog::Create(MReanimatable* parent)
  248. {
  249.     ASSERT(parent == nil);
  250.     
  251.     if (CWindowProxy::msUseProxy)
  252.         return CDialogBoxProxy::Create(parent);
  253.     else
  254.         return new CPenDialog;
  255. }
  256.  
  257.  
  258. //---------------------------------------------------------------
  259. //
  260. // CPenDialog::Pose                                        [static]
  261. //
  262. //---------------------------------------------------------------
  263. bool CPenDialog::Pose(const string& penName, const SPen& oldPen, SPen* newPen)
  264. {
  265.     ASSERT(newPen != nil);
  266.     
  267.     CPenDialog* dialog = dynamic_cast<CPenDialog*>(TDialogBox::Create(242, TApplication::Instance()));
  268.     
  269.     dialog->SetData(oldPen);
  270.     dialog->SetName(penName);
  271.     
  272.     string message = kNothingMessage;
  273.                 
  274.     {
  275.     TDialogHandler handler(dialog);
  276.         dialog->Show();
  277.                 
  278.         while (message != kCancelMessage && message != kOKMessage) {
  279.             message = handler.ProcessNextEvent();
  280.             
  281.             if (message == kOKMessage && !dialog->Validate())
  282.                 message = kNothingMessage;
  283.         }
  284.     }
  285.     
  286.     if (message == kOKMessage)
  287.         *newPen = dialog->GetData();
  288.     
  289.     return message == kOKMessage;
  290. }
  291.  
  292.  
  293. //---------------------------------------------------------------
  294. //
  295. // CPenDialog::HandleMouseDown
  296. //
  297. //---------------------------------------------------------------
  298. bool CPenDialog::HandleMouseDown(const TMouseEvent& event)
  299. {
  300.     PRECONDITION(true);
  301.     
  302.     TColorSwatch* swatch1 = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
  303.     ASSERT(swatch1 != nil);
  304.     
  305.     TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
  306.     ASSERT(swatch2 != nil);
  307.     
  308.     TRGBColor color = swatch1->GetColor();
  309.     Pattern pattern = swatch2->GetPattern();
  310.     
  311.     bool handled = Inherited::HandleMouseDown(event);
  312.     
  313.     // We can't use CClickNotifier because we need to call SetData
  314.     // after the swatch handles the click.
  315.     if (handled && (swatch1->GetColor() != color) || (swatch2->GetPattern() != pattern)) {
  316.         SPen traits = this->GetData();
  317.         
  318.         this->SetData(traits);
  319.     }
  320.         
  321.     POSTCONDITION(true);
  322.     
  323.     return handled;
  324. }
  325.  
  326.  
  327. //---------------------------------------------------------------
  328. //
  329. // CPenDialog::HandleContextMenu
  330. //
  331. //---------------------------------------------------------------
  332. bool CPenDialog::HandleContextMenu(const TMouseEvent& event)
  333. {
  334.     PRECONDITION(true);
  335.     
  336.     TColorSwatch* swatch1 = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
  337.     ASSERT(swatch1 != nil);
  338.     
  339.     TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
  340.     ASSERT(swatch2 != nil);
  341.     
  342.     TRGBColor color = swatch1->GetColor();
  343.     Pattern pattern = swatch2->GetPattern();
  344.     
  345.     bool handled = Inherited::HandleContextMenu(event);
  346.     
  347.     // Swatch commands post a command to perform the change.
  348.     if (handled && TCommand::ExecuteCommands(true))
  349.         TMenuBar::Invalidate();
  350.  
  351.     // We can't use CClickNotifier because we need to call SetData
  352.     // after the swatch handles the click.
  353.     if (handled && (swatch1->GetColor() != color) || (swatch2->GetPattern() != pattern)) {
  354.         SPen traits = this->GetData();
  355.         
  356.         this->SetData(traits);
  357.     }
  358.         
  359.     POSTCONDITION(true);
  360.     
  361.     return handled;
  362. }
  363.  
  364.  
  365. #pragma mark ハ
  366.  
  367. //---------------------------------------------------------------
  368. //
  369. // CPenDialog::OnReanimated
  370. //
  371. //---------------------------------------------------------------
  372. void CPenDialog::OnReanimated()
  373. {
  374.     Inherited::OnReanimated();
  375.     
  376.     CRandomWalk* walk = dynamic_cast<CRandomWalk*>(this->FindSubPane("Random Walk"));
  377.     walk->AddBehaviorToFront(new CClickNotifier(this, "Clicked Walk"));
  378.  
  379.     TTextBox* textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Width"));
  380.     textbox->AddListener(this);
  381.     
  382.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Height"));
  383.     textbox->AddListener(this);
  384.     
  385.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("PixPat ID"));
  386.     textbox->AddListener(this);
  387.     
  388.     TSubPaneIterator iter = this->begin(kRecursive);
  389.     while (iter != this->end()) {
  390.         TPane* subPane = *iter;
  391.         ++iter;
  392.         
  393.         if (TControl* control = dynamic_cast<TControl*>(subPane))
  394.             if (dynamic_cast<TPushButton*>(control) == nil)            // we're already listening to the push buttons
  395.                 control->AddListener(this);
  396.     }    
  397. }
  398.  
  399.  
  400. //---------------------------------------------------------------
  401. //
  402. // CPenDialog::OnBroadcast (SControlMessage)
  403. //
  404. //---------------------------------------------------------------
  405. void CPenDialog::OnBroadcast(const SControlMessage& mesg)
  406. {
  407.     Inherited::OnBroadcast(mesg);
  408.     
  409.     if (dynamic_cast<TPushButton* const>(mesg.control) == nil) {
  410.         SPen pen = this->GetData();
  411.     
  412.         this->SetData(pen);
  413.     }
  414. }
  415.  
  416.  
  417. //---------------------------------------------------------------
  418. //
  419. // CPenDialog::OnBroadcast (TTextBox*)
  420. //
  421. //---------------------------------------------------------------
  422. void CPenDialog::OnBroadcast(TTextBox* const& mesg)
  423. {
  424.     if (mesg->GetTextLength() > 0) {
  425.         SPen pen = this->GetData();
  426.     
  427.         this->SetData(pen);
  428.     }
  429. }
  430.  
  431.  
  432. //---------------------------------------------------------------
  433. //
  434. // CPenDialog::OnMenuCommand
  435. //
  436. //---------------------------------------------------------------
  437. bool CPenDialog::OnMenuCommand(const MenuCommand& command)
  438. {
  439.     bool handled = true;
  440.     
  441.     if (command == "Clicked Walk") {
  442.         CRandomWalk* walk = dynamic_cast<CRandomWalk*>(this->FindSubPane("Random Walk"));
  443.         walk->Restart();
  444.  
  445.     } else
  446.         handled = Inherited::OnMenuCommand(command);
  447.         
  448.     return handled;
  449. }
  450.  
  451.  
  452. //---------------------------------------------------------------
  453. //
  454. // CPenDialog::SetData
  455. //
  456. //---------------------------------------------------------------
  457. void CPenDialog::SetData(const SPen& pen)
  458. {    
  459.     TTextBox* textbox = nil;
  460.     
  461.     // Width
  462.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Width"));
  463.     textbox->SetValue(pen.size.width);
  464.     
  465.     // Height
  466.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Height"));
  467.     textbox->SetValue(pen.size.height);
  468.     
  469.     // Mode
  470.     TControl* control = dynamic_cast<TControl*>(this->FindSubPane("Mode"));
  471.     control->SetValue(pen.mode - patCopy + 1);
  472.     
  473.     // Color
  474.     TColorSwatch* swatch1 = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
  475.     swatch1->SetColor(pen.color);
  476.  
  477.     // Pattern
  478.     TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
  479.     swatch2->SetPattern(pen.pattern);
  480.  
  481.     // PixPat ID
  482.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("PixPat ID"));
  483.     textbox->SetValue(pen.pixPatID);
  484.     
  485.     // Walker
  486.     CRandomWalk* walk = dynamic_cast<CRandomWalk*>(this->FindSubPane("Random Walk"));
  487.     walk->SetPen(pen);
  488. }
  489.  
  490.  
  491. //---------------------------------------------------------------
  492. //
  493. // CPenDialog::GetData
  494. //
  495. //---------------------------------------------------------------
  496. SPen CPenDialog::GetData() const
  497. {    
  498.     SPen pen;
  499.  
  500.     TTextBox* textbox = nil;
  501.         
  502.     // Width
  503.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Width"));
  504.     pen.size.width = textbox->GetValue();
  505.     
  506.     // Height
  507.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Height"));
  508.     pen.size.height = textbox->GetValue();
  509.     
  510.     // Mode
  511.     TControl* control = dynamic_cast<TControl*>(this->FindSubPane("Mode"));
  512.     pen.mode = control->GetValue() + patCopy - 1;
  513.     
  514.     // Color
  515.     TColorSwatch* swatch = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
  516.     pen.color = swatch->GetColor();
  517.  
  518.     // Pattern
  519.     TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
  520.     pen.pattern = swatch2->GetPattern();
  521.  
  522.     // PixPat ID
  523.     textbox = dynamic_cast<TTextBox*>(this->FindSubPane("PixPat ID"));
  524.     pen.pixPatID = textbox->GetValue();
  525.     
  526.     if (pen.pixPatID != 0)
  527.         pen.pixPat = GetPixPat(pen.pixPatID);        // ignore errors
  528.         
  529.     return pen;
  530. }
  531.  
  532.  
  533.  
  534.  
  535.